package com.example.mybatis.plugin;

import com.example.mybatis.util.EncUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
@Component
@Intercepts({
        @Signature(type = ParameterHandler.class,method = "setParameters",args = {PreparedStatement.class}),
        @Signature(type = Executor.class,method = "update",args = {MappedStatement.class,Object.class})
})
public class EncInterceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        for(int i=0;i<args.length;i++){
           Object arg = args[i];
            if(arg instanceof MappedStatement){
                log.info("测试");
            }else if(arg instanceof MapperMethod.ParamMap){
                Map map=(Map)args[1];
                log.info("参数长度"+map.size());
                log.info(arg.toString());
                Set<String> strings = ((MapperMethod.ParamMap<?>) arg).keySet();
                for(String key:strings){
                    if(key.equals("password")||key.equals("param1")) {
                        log.info(key + "==" + ((MapperMethod.ParamMap<?>) arg).get(key));
                        log.info(String.valueOf(((MapperMethod.ParamMap<?>) arg).get(key) instanceof String));
                        System.out.println(((MapperMethod.ParamMap<?>) arg).get(key) instanceof String);
                        String s = ((MapperMethod.ParamMap<?>) arg).get(key).toString();
                        String encData = EncUtil.getMd5(s);
                        map.put(key,encData);
                    }
                }
            }
        }
        if(invocation.getTarget() instanceof ParameterHandler){
            //获取代理的参数对象
            ParameterHandler ph=(ParameterHandler)invocation.getTarget();
            // 通过MetaObject获取ParameterHandler的反射内容
            MetaObject metaObject = MetaObject.forObject(ph, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                                    SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
            // 通过MetaObject反射的内容获取MappedStatement
            MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("mappedStatement");
            // 当sql类型为INSERT或UPDATE时，自动插入操作员信息
            log.info("操作类型为："+mappedStatement.getSqlCommandType());
                    if (mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {
                        // 获取参数对象
                        Object obj = ph.getParameterObject();
                        if(obj!=null){
                            Field[] declaredFields = obj.getClass().getDeclaredFields();
                            for(Field fd:declaredFields){
                                log.info("属性名"+fd.getName());
                                // 设置允许访问反射属性
                                fd.setAccessible(true);
                                if(fd.getName().equals("password")){
                                    log.info("属性名为"+fd.getName());
                                    log.info("原始密码为："+fd.get(obj));
                                    fd.set(obj, EncUtil.getMd5((String)(fd.get(obj))));
                                }
                            }

                        }
                    }else if(mappedStatement.getSqlCommandType()==SqlCommandType.UPDATE){
                      //  ParameterHand parameterObject =(ParameterObject) metaObject.getValue("parameterObject");
                    }



        }
        return invocation.proceed();
    }
}
